package com.bawei.es.service.impl;

import com.bawei.common.core.domain.R;
import com.bawei.common.core.exception.ServiceException;
import com.bawei.common.core.utils.StringUtils;
import com.bawei.es.service.EsIndexService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.ReindexRequest;
import org.elasticsearch.script.Script;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class EsIndexServiceImpl implements EsIndexService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;


    @Override
    public R<Boolean> indexCreates(String indexName, Map<String, Object> settings) {
        try {
            // 使用Elasticsearch客户端创建索引，包括settings
            CreateIndexRequest request = new CreateIndexRequest(indexName).settings(settings);
            // 调用Elasticsearch客户端执行请求
            CreateIndexResponse acknowledged = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
            if (acknowledged.isAcknowledged()) {
                return R.ok(true,"创建成功"+indexName);
            }
        } catch (IOException e) {
            // 处理异常
            log.error("连接ES服务异常:{}", e);
            throw new RuntimeException("创建索引失败，请联系管理员或查看服务日志");
        }
        return R.fail(false, "索引创建失败");
    }

    @Override
    public R<Boolean> indexExit(String indexName) {
        if (StringUtils.isEmpty(indexName)) {
            throw new ServiceException("indexName不能为空");
        }
        GetIndexRequest indexRequest = new GetIndexRequest(indexName);
        try {
            boolean exists = restHighLevelClient.indices().exists(indexRequest, RequestOptions.DEFAULT);
            return R.ok(exists,"查询成功,索引存在");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.fail(false, "查询失败,索引不存在！");
    }

    @Override
    public R<Boolean> indexDelete(String indexName) {
        if (StringUtils.isEmpty(indexName)) {
            throw new ServiceException("indexName不能为空 ");
        }
        DeleteIndexRequest request = new DeleteIndexRequest(indexName);
        try {
            AcknowledgedResponse delete = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
            if (delete.isAcknowledged()) {
                return R.ok(true, "删除成功！");
            }
        } catch (IOException e) {
            log.error("删除索引失败：{}", e);
            throw new RuntimeException("调用es服务删除索引失败，详情请查看日志");
        }
        return R.fail(false, "删除索引失败");
    }

    @Override
    public R<Boolean> indexCreateWithMapping(String indexName, String indexMapping) {
        if (StringUtils.isEmpty(indexName) ||
                StringUtils.isEmpty(indexMapping)) {
            throw new ServiceException("indexName、indexMapping不能为空");
        }
        CreateIndexRequest request =  new CreateIndexRequest(indexName);
        request.source(indexMapping, XContentType.JSON);
        try {
            CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
            if (createIndexResponse.isAcknowledged()){
                return R.ok(true,"创建索引成功");
            }
        } catch (IOException e) {
            log.error("调用es创建索引异常：{}",e);
            throw new RuntimeException("创建索引失败");
        }

        return R.fail(false,"创建索引失败");
    }

    @Override
    public R<Map<String,Object>> indexGetMapping(String indexName) {
        if (StringUtils.isEmpty(indexName)){
            throw new ServiceException("indexName不能为空");
        }

        try {
            // 创建一个GetIndexRequest对象，用于获取索引的settings和mappings
            GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);

            // 执行请求，获取GetIndexResponse
            GetIndexResponse getIndexResponse = restHighLevelClient.indices().get(getIndexRequest, RequestOptions.DEFAULT);

            // 提取settings
            Settings settings = getIndexResponse.getSettings().get(indexName);
            Map<String, Object> settingsMap = new HashMap<>();
            settings.keySet().forEach(key -> settingsMap.put(key, settings.get(key)));

            // 提取mappings
            Map<String, MappingMetaData> mappings = getIndexResponse.getMappings();
            MappingMetaData mappingMetaData = mappings.get(indexName);
            Map<String, Object> mappingMap = mappingMetaData.sourceAsMap();

            // 将settings和mappings存储在一个结果Map中
            Map<String, Object> result = new HashMap<>();
            result.put("settings", settingsMap);
            result.put("mappings", mappingMap);

            return R.ok(result, "操作成功");
        } catch (IOException e) {
            log.error("根据索引名称获取Mapping和Settings异常:{}", e);
            throw new RuntimeException("根据索引名称获取Mapping和Settings异常");
        }
    }

    @Override
    public List<String> findIndex() {
            List<String> list = new ArrayList<>();
            GetIndexRequest request = new GetIndexRequest("_all"); // "_all" 表示所有索引
            GetIndexResponse getIndexResponse = null;
            try {
                getIndexResponse = restHighLevelClient.indices().get(request, RequestOptions.DEFAULT);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            // 从响应中提取索引名列表
            for (String index : getIndexResponse.getIndices()) {
                list.add(index);
            }
            return list;
        }

    @Override
    public void reindexWithNewFields(String sourceIndex, String targetIndex, Script script) throws IOException {
        // 检查目标索引是否存在，如果不存在则创建它
        if (!existsIndex(targetIndex)) {
            // 这里你可以定义目标索引的mappings和settings
            // 创建一个CreateIndexRequest并设置mappings等
            // client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
            // 由于示例中我们不关注完整的mappings创建，这里仅假设目标索引已存在或会自动创建
        }

        // 创建ReindexRequest
        ReindexRequest request = new ReindexRequest();
        request.setSourceIndices(sourceIndex);
        request.setDestIndex(targetIndex);

        // 如果提供了脚本，则添加到请求中
        if (script != null) {
            request.setScript(script);
        }

        // 执行reindex操作
        BulkByScrollResponse reindexResponse  = restHighLevelClient.reindex(request, RequestOptions.DEFAULT);

        // 你可以根据需要处理reindexResponse，例如检查失败的文档等
        // ...
    }

    private boolean existsIndex(String index) throws IOException {
        GetIndexRequest request = new GetIndexRequest(index);
        return restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
    }
}
